package com.shadow.demo.dictionary.common;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.*;

/**
 * 集合工具类
 *
 * @author penggch
 */
public class CollectionUtil {

    /**
     * 将链表转为数组
     *
     * @param <T>
     * @param cls         类型
     * @param collections 链表
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T[] toArray(Class<T> cls, Collection<T> collections) {
        if (collections == null) {
            return null;
        }
        T[] arr = (T[]) Array.newInstance(cls, collections.size());
        int i = 0;
        for (T t : collections) {
            arr[i] = t;
            i++;
        }
        return arr;
    }

    /**
     * 将对象转为数组
     *
     * @param <T>
     * @param cls 类型
     * @param obj 对象
     * @return
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static <T> T[] toArray(Class<T> cls, Object obj) {
        if (obj == null) {
            return null;
        }
        T[] arr = null;
        if (obj.getClass().isArray()) {
            arr = (T[]) Array.newInstance(cls, Array.getLength(obj));
            for (int i = 0; i < arr.length; i++) {
                arr[i] = (T) Array.get(obj, i);
            }
        } else if (obj instanceof Collection) {
            Collection collection = (Collection) obj;
            int idx = 0;
            arr = (T[]) Array.newInstance(cls, collection.size());
            for (Object item : collection) {
                arr[idx] = (T) item;
                idx++;
            }
        }
        return arr;
    }

    /**
     * 将数组转为链表
     *
     * @param <T>
     * @param cls   类型
     * @param array 数组
     * @return
     */
    public static <T> List<T> toList(Class<T> cls, T[] array) {
        if (array == null) {
            return null;
        }
        return Arrays.asList(array);
    }

    /**
     * 将对象转为链表
     *
     * @param <T>
     * @param cls 类型
     * @param obj 对象
     * @return
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static <T> List<T> toList(Class<T> cls, Object obj) {
        if (obj == null) {
            return null;
        }
        List<T> list = null;
        if (obj.getClass().isArray()) {
            list = new ArrayList<T>(Array.getLength(obj));
            for (int i = 0; i < list.size(); i++) {
                list.add((T) Array.get(obj, i));
            }
        } else if (obj instanceof Collection) {
            Collection collection = (Collection) obj;
            list = new ArrayList<T>(Array.getLength(collection.size()));
            for (Object item : collection) {
                list.add((T) item);
            }
        }
        return list;
    }

    /**
     * 合并数组
     *
     * @param <T>
     * @param cls 类型
     * @param ts  待合并的数组
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T[] merge(Class<T> cls, T[]... ts) {
        return merge(cls, false, ts);
    }

    /**
     * 合并数组
     *
     * @param <T>
     * @param cls         类型
     * @param removeEmpty 是否移除空对象，true:移除；false:不移除
     * @param ts          待合并的数组
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T[] merge(Class<T> cls, boolean removeEmpty, T[]... ts) {
        int len = 0;
        if (ts != null && ts.length > 0) {
            for (T[] t : ts) {
                if (t == null) {
                    continue;
                }
                if (removeEmpty) {
                    for (T ti : t) {
                        if (!isEmpty(ti)) {
                            len++;
                        }
                    }
                } else {
                    len += t.length;
                }

            }
        }
        T[] rs = (T[]) Array.newInstance(cls, len);
        if (len > 0) {
            int idx = 0;
            for (T[] t : ts) {
                if (t == null) {
                    continue;
                }
                for (T ti : t) {
                    rs[idx] = ti;
                    idx++;
                }
            }
        }
        return rs;
    }

    /**
     * 清理数组中的空数据
     *
     * @param <T>
     * @param cls 类型
     * @param ts  待清理的数组
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T[] cleanEmpty(Class<T> cls, T[] ts) {
        List<T> list = new ArrayList<T>();
        for (T t : ts) {
            if (isEmpty(t)) {
                continue;
            }
            list.add(t);
        }
        T[] rs = (T[]) Array.newInstance(cls, list.size());
        return list.toArray(rs);
    }

    @SuppressWarnings("rawtypes")
    private static boolean isEmpty(Object value) {
        return value == null
                || (value instanceof String && ((String) value).length() == 0)
                || (value.getClass().isArray() && Array.getLength(value) == 0)
                || (value instanceof Collection && ((Collection) value).size() == 0);
    }

    public static Map<String, Map<String, Object>> resolveKeyData(String keyData) {
        Map<String, Map<String, Object>> result = new HashMap<String, Map<String, Object>>();
        if (keyData == null || keyData.length() == 0) {
            return result;
        }
        JSONObject json = JSON.parseObject(keyData);
        for (String key : json.keySet()) {
            JSONObject v = json.getJSONObject(key);
            Map<String, Object> map = JsonUtil.convertToMap(v);
            if (map != null) {
                result.put(key, map);
            }
        }
        return result;
    }

    public static Map<String, List<Object>> resolveObjectData(String data) {
        Map<String, List<Object>> result = new HashMap<>();
        if (StringUtils.isEmpty(data)) {
            return result;
        }
        JSONObject json = JSON.parseObject(data);
        for (String key : json.keySet()) {
            String v = json.getString(key);
            List<Map<String, Object>> list = JsonUtil.convertToListMap(v);
            List<Object> objList = new ArrayList<>(list);
            result.put(key, objList);
        }
        return result;
    }

    public static Map<String, List<Map<String, Object>>> resolveData(String data) {
        Map<String, List<Map<String, Object>>> result = new HashMap<String, List<Map<String, Object>>>();
        if (data == null || data.length() == 0) {
            return result;
        }

        JSONObject json = JSON.parseObject(data);
        for (String key : json.keySet()) {
            String v = json.getString(key);
            List<Map<String, Object>> list = JsonUtil.convertToListMap(v);
            result.put(key, list);
        }
        return result;
    }

    public static Map<String, String> resolveLogKeyData(String logKeyData) {
        Map<String, String> result = new HashMap<String, String>();
        if (logKeyData == null || logKeyData.length() == 0) {
            return result;
        }
        JSONObject json = JSON.parseObject(logKeyData);
        for (String key : json.keySet()) {
            String v = json.getString(key);
            if (v == null || v.length() == 0) {
                continue;
            }
            result.put(key, v);
        }
        return result;
    }

    public static Map<String, List<Map<String, Object>>> toDetailMap(Map<String, List<Object>> map) {
        Map<String, List<Map<String, Object>>> dataMap = new HashMap<String, List<Map<String, Object>>>();
        for (Map.Entry<String, List<Object>> entry : map.entrySet()) {
            Object o = entry.getValue();
            if (o instanceof List) {
                dataMap.put(entry.getKey(), (List<Map<String, Object>>) o);
            } else {
                List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
                list.add((Map<String, Object>) o);
                dataMap.put(entry.getKey(), list);
            }
        }
        return dataMap;
    }

    /**
     * 判断集合是否为空
     *
     * @param coll
     * @return true 表示集合为空
     * @author
     */
    public static boolean isEmptys(Collection<?> coll) {
        return coll == null
                || coll.isEmpty()
                || coll.size() == 0;
    }

    private static boolean isEqual(Object value1, Object value2) {
        boolean result = false;
        if (value1 == null && value2 == null) {
            result = true;
        } else if (value1 != null && value2 != null) {
            String className1 = value1.getClass().getName();
            String className2 = value2.getClass().getName();
            if (className1.equals(className2)) {
                Method method = ReflectUtil.getEqualsMethod(value1.getClass());
                if (method != null) {
                    if (className1.equals(Double.class.getName())) {
                        Double double1 = (Double) value1;
                        Double double2 = (Double) value2;
                        if ((double1 > 0 && double2 > 0) || (double1 < 0 && double2 < 0)) {
                            result = Math.abs(double1 - double2) < 0.00000000000001;
                        }
                    } else if (className1.equals(Float.class.getName())) {
                        Float float1 = (Float) value1;
                        Float float2 = (Float) value2;
                        if ((float1 > 0 && float2 > 0) || (float1 < 0 && float2 < 0)) {
                            result = Math.abs(float1 - float2) < 0.00000000000001;
                        }
                    } else {
                        try {
                            result = (boolean) method.invoke(value1, value2);
                        } catch (Exception e) {
                            throw new RuntimeException(e.getMessage(), e);
                        }
                    }
                } else if (className1.equals("double")) {
                    double double1 = (double) value1;
                    double double2 = (double) value2;
                    if ((double1 > 0 && double2 > 0) || (double1 < 0 && double2 < 0)) {
                        result = Math.abs(double1 - double2) < 0.00000000000001;
                    }
                } else if (className1.equals("float")) {
                    float float1 = (float) value1;
                    float float2 = (float) value2;
                    if ((float1 > 0 && float2 > 0) || (float1 < 0 && float2 < 0)) {
                        result = Math.abs(float1 - float2) < 0.00000000000001;
                    }
                } else {
                    result = value1 == value2;
                }
            }
        }
        return result;
    }

    /**
     * 判断source是否包含items，items中的所有内容在source中都存在
     *
     * @param source
     * @param items
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static boolean contains(Object source, Object items) {
        boolean result = false;
        if (isEmpty(source) || isEmpty(items)) {
            result = false;

        } else if (source instanceof String && items instanceof String) {
            result = ((String) source).contains((String) items);

        } else if (isArray(source)) {
            result = arrayContains(source, items);

        } else if (isCollection(source)) {
            result = contains((Collection) source, items);

        }
        return result;
    }

    @SuppressWarnings("rawtypes")
    private static boolean contains(Collection collection, Object items) {
        boolean result = false;
        if (isArray(items)) {
            int len = Array.getLength(items);
            result = true;
            for (int i = 0; i < len; i++) {
                Object item = Array.get(items, i);
                if (!collection.contains(item)) {
                    result = false;
                    break;
                }
            }

        } else if (isCollection(items)) {
            Collection itemCollection = (Collection) items;
            result = true;
            for (Object item : itemCollection) {
                if (!collection.contains(item)) {
                    result = false;
                    break;
                }
            }
        } else {
            result = collection.contains(items);

        }
        return result;
    }

    @SuppressWarnings("rawtypes")
    private static boolean arrayContains(Object array, Object items) {
        boolean result = false;
        if (isArray(items)) {
            int len = Array.getLength(items);
            result = true;
            for (int i = 0; i < len; i++) {
                Object item = Array.get(items, i);
                if (!arrayContainsItem(array, item)) {
                    result = false;
                    break;
                }
            }

        } else if (isCollection(items)) {
            Collection itemCollection = (Collection) items;
            result = true;
            for (Object item : itemCollection) {
                if (!arrayContainsItem(array, item)) {
                    result = false;
                    break;
                }
            }
        } else {
            result = arrayContainsItem(array, items);

        }
        return result;
    }

    private static boolean arrayContainsItem(Object array, Object item) {
        int alen = Array.getLength(array);
        boolean result = false;
        for (int i = 0; i < alen; i++) {
            Object obj = Array.get(array, i);
            if (isEqual(obj, item)) {
                result = true;
                break;
            }
        }
        return result;
    }

    /**
     * 是否是数组
     *
     * @param value
     * @return
     */
    public static boolean isArray(Object value) {
        return value != null && value.getClass().isArray();
    }

    /**
     * 是否是集合
     *
     * @param value
     * @return
     */
    public static boolean isCollection(Object value) {
        return value instanceof Collection;
    }

}